/**
  ******************************************************************************
  * @file           : rpc_client.cpp
  * @author         : chyang
  * @brief          : None
  * @attention      : None
  * @date           : 2024/3/13
  ******************************************************************************
*/
#include "rpc_client.h"

OcrRec::OcrRec(std::string IpAndPort) {
    //同样的，获得一个线路频道
    auto channel = grpc::CreateChannel(IpAndPort, grpc::InsecureChannelCredentials());
    //连接并获得远程函数指针
    stu_ = data::NewStub(channel);
}

bool OcrRec::RunOcr(RResult &res) {
    if (res.res_img.empty()) {
        res.info = "res_img.empty()!";
        return false;
    }

    cv::Mat cvImag = res.res_img.clone();
    ClientContext context;
    data_request reqImg;
    data_reply retImg;

    std::vector<uchar> data_encode;
    //把图片编码成字符串，opencv里面的，很叼的一个函数
    cv::imencode(".jpg", cvImag, data_encode);
    //再变成一个vector
    std::string data_str = std::string(data_encode.begin(), data_encode.end());

    Base64 b64;
    //base64编码
    std::string bs64 = b64.Encode((unsigned char *) data_str.c_str(), data_str.length());
    //放到我们要调用远程函数的参数里面去
    reqImg.set_cmd(bs64);


    if (!stu_) {
        res.info = "grpc is not init!";
        return false;
    }
    //开始调用远程函数,reqImg是实参，retImg是返回值,context是个什么鬼不知道，但是必须有（应该是个凭证，不然不知道谁调用它）
    grpc::Status status = stu_->serving(&context, reqImg, &retImg);
    if (status.ok()) {
        std::cout << "sucesses!";
    } else {
        std::cout << "错误代码：" << status.error_code() << "\n错误信息:" << status.error_message();
        res.info = status.error_message();
        return false;
    }

    //获取返回来的字符串长度
    int str_len = retImg.mutable_values()->length();
    if (str_len <= 0) {
        std::cout << "Error!,str_len<0";
        res.info = "Rpc back char is null";
        return false;
    }

    //开个内存
    char *dec_rec = new char[str_len];

    if (!dec_rec) {
        std::cout << "Error!,in do malloc char[str_len]";
        res.info = "malloc failed";
        return false;
    }
    //把内存全部置0,以免烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫
    memset(dec_rec, 0, str_len);
    //拷贝函数返回的字符串到变量中
    memcpy(dec_rec, retImg.mutable_values()->c_str(), str_len);

    //把base64解码，变成字符串。因为网络传输是base64位的
    std::string dstr64 = b64.Decode(dec_rec, str_len);
    //再把字符串变成一个uchar的vector
    std::vector<uchar> data(dstr64.begin(), dstr64.end());
    cv::Mat rec_img;
    rec_img = cv::imdecode(data, 1);
    if (rec_img.empty()) {
        res.info = "rec_img is empty";
        return false;
    }

    res.res_img = rec_img.clone();
    delete dec_rec;
    dec_rec = nullptr;
    return true;
}